/*
 * Serum
 *
 * @license      GNU Lesser General Public Licence see LICENCE-LGPL file or http://www.gnu.org/licenses/lgpl.html
 */

Serum.Form.Module.Edit = Ext.extend(Serum.Form.Module.Abstract, {

    /**
     * Constructor
     */
    constructor: function(config, selector, onSuccess) {
        this.elementId  = null;

        if (typeof selector === 'undefined') {
            selector = {};
        }

        this.module             = (typeof selector.module !== 'undefined')      ? selector.module       : Serum.Selector.get().module;
        this.controller         = (typeof selector.controller !== 'undefined')  ? selector.controller   : Serum.Selector.get().controller;
        this.action             = (typeof selector.action !== 'undefined')      ? selector.action       : Serum.Selector.get().action;
        this.language           = (typeof selector.language !== 'undefined')    ? selector.language     : Serum.Selector.get().language;
        this.parentRoot         = (typeof selector.parentRoot !== 'undefined')  ? selector.parentRoot   : Serum.Selector.get().getParams['parentRoot'];
        this.saveAction         = (typeof selector.saveAction !== 'undefined')  ? selector.saveAction   : 'save';
        this.onSuccessHandler   = (typeof onSuccess === 'function')             ? onSuccess             : this.onSuccess;

        Serum.Form.Module.Edit.superclass.constructor.call(this, Ext.apply({
            labelWidth:     140,
            plugins:        [new Ext.ux.form.FieldAutoExpand()],
            border:         false,
            fileUpload:     true,
            autoScroll:     true,

            layout:         'form',
            bodyStyle:      'padding: 15px 30px 15px 15px;',
            tbar:            this.getTopToolbar(),

            defaultType:    'textfield',
            monitorValid:   true,
            items:          [],

            keys: [{
                key:    Ext.EventObject.ENTER,
                fn:     this.submitForm,
                scope:  this
            }],

            buttons: [{
                scope:      this,
                type:       'submit',
                text:       __('base~form_validate'),

                handler: function() {
                    this.submitForm();
                }
            }]

        }, config));
    },

    /**
     * Returns form title
     *
     * @return  {String}
     */
    getTitle: function() {
        return __(this.module.toLowerCase() + '~form_title', 'base~form_title');
    },

    /**
     * Returns the top toolbar
     */
    getTopToolbar: function() {

        var toolbar         = new Array();
        var comboArray      = new Array();
        var _languages      = Serum.Languages.get().getValues();
        var currentCountry  = null;
        var currentLanguage = null;
        var currentIso      = null;
        var currentElement  = null;

        for (var _country in _languages) {
            currentCountry  = _languages[_country];

            for (var _language in currentCountry['DbLanguage']) {
                currentLanguage = currentCountry['DbLanguage'][_language];
                currentIso      = currentLanguage['code'] + '_' + currentCountry['code'];
                currentElement  = new Array();

                currentElement.push(currentIso, currentLanguage['name']);

                comboArray.push(currentElement);
            }
        }

        if (comboArray.length > 1) {

            // Filler
            toolbar.push('->');

            // Language combo box
            var comboStore = new Ext.data.SimpleStore({
                fields: ['iso', 'name'],
                data : comboArray
            });

            toolbar.push(new Ext.form.ComboBox({
                                hiddenName:         'name',
                                store:              comboStore,
                                mode:               'local',
                                displayField:       'name',
                                valueField:         'iso',
                                fieldLabel:         __('base~form_label_languages'),
                                emptyText:          __('base~form_label_languages'),
                                forceSelection:     true,
                                allowBlank:         false,
                                editable:           true,
                                typeAhead:          false,
                                value:              Serum.Selector.get().language,
                                id:                 'element-language',
                                listeners:
                                {
                                    select: function(thisComboBox, thisCaption, thisIndex) {
                                            Serum.Selector.get().set({ language: thisComboBox.value }, false);
                                        }
                                }

            }));

            return toolbar;
        } else {
            return null;
        }
    },

    /**
     * Returns true if current element is being edited
     *
     * @return  {Boolean}
     */
    isEditForm: function() {
        return ['edit', 'editParent'].contains(Serum.Selector.get().action);
    },

    /**
     * Returns true if current element is being added
     *
     * @return  {Boolean}
     */
    isAddForm: function() {
        return ['add', 'addParent'].contains(Serum.Selector.get().action);
    },

    isFormAction: function() {
        return (this.isEditForm() || this.isAddForm());
    },

    /**
     * Preloads form items (delete former items)
     *
     * @param   {Mixed} elementId
     */
    preload: function(elementId) {
        this.elementId = null;

        if (typeof elementId !== 'undefined') {
            this.elementId = elementId;

        } else if (typeof Serum.Selector.get().getParams['id'] !== 'undefined' && this.isEditForm()) {
            this.elementId = Serum.Selector.get().getParams['id'];
        }

        if (typeof this.items !== 'undefined') {
            var i;
            while(i = this.items.last()) {
                this.remove(i, true);
            }
        }
    },

    /**
     * Loads form items
     *
     * @param   {Object}    fieldsList
     */
    load: function(fieldsList) {
        this.build(fieldsList);
    },

    /**
     * Builds the form
     *
     * @param   {Object}    fieldsList
     */
    build: function(fieldsList) {
        var elementId   = this.getElementId();

        // Initializes request params
        var _params = {
            method: Serum.Selector.get().method({
                module:     this.module,
                controller: this.controller,
                action:     this.action
            }),
            requestId: Serum.Helper.Request.id()
        };

        if (elementId !== null) {
            if (elementId instanceof Array) {
                _params['elementIdList']    = elementId.implode('-');
            } else {
                _params['elementId']        = elementId;
            }
        }

        if (typeof this.parentRoot !== 'undefined') {
            _params['parentRoot'] = this.parentRoot;

        } else if (typeof Serum.Selector.get().getParams['modelRoot'] !== 'undefined') {
            _params['modelRoot'] = Serum.Selector.get().getParams['modelRoot'];
        }

        // Current language
        _params['language'] = Serum.Selector.get().language;

        // Ajax request to get fields list
        Serum.Ajax.request({
            scope:       this,
            params:     _params,
            onSuccess:  function(response) {
                            var jsonResponse = Ext.util.JSON.decode(response.responseText);

                            if (typeof jsonResponse['result']['fields'] !== 'undefined') {
                                this._build(jsonResponse['result'], fieldsList);
                            }
                        }
        });
    },

    /**
     * Requests server and processes returned errors
     *
     * @param       {Object}        extraParams
     */
    submitForm: function(extraParams) {
        if (typeof extraParams === 'undefined') {
            extraParams = {};
        }
        extraParams.language    = this.language;

        this.form.submit({
            method:     'POST',
            url:        Serum.Selector.get().requestUrl('index'),
            params:     Ext.apply({
                                    method: Serum.Selector.get().method({
                                                                            module:     this.module,
                                                                            controller: this.controller,
                                                                            action:     this.saveAction
                                                                        })
                        }, extraParams),
            waitTitle:  __('base~form_waitTitle'),
            waitMsg:    __('base~form_waitMsg'),

            success:    this.onSuccessHandler,
            failure:    this.onFailure,
            scope:      this
        });
    },

    /**
     * Called after a successful form submit.
     *
     * @param   {Ext.form.BasicForm}    form        Submitted form
     * @param   {Object}                action      Returned value
     */
    onSuccess: function(form, action) {
        Serum.Message.Validate.display(__(this.module+'~'+this.action+'_valid_title','base~'+this.action+'_valid_title'), __(this.module+'~'+this.action+'_valid_content','base~'+this.action+'_valid_content'));
        Serum.Selector.get().set({action: 'index', id: null}, false);
    },

    /**
     * Called after a failed form submit.
     *
     * @param   {Ext.form.BasicForm}    form        Submitted form
     * @param   {Object}                action      Returned value
     */
    onFailure: function(form, action) {
        Serum.Message.Error.display(__('base~form_errors_title'), __('base~form_errors_description'));

        if (action['failureType'] == 'server') {
            var response    = Ext.util.JSON.decode(action['response']['responseText']);
            var errors      = response['errors'];

            if (typeof response['exception'] !== 'undefined') {
                Serum.Exception.Handler.process(response['exception']);
            }

            for(var error in errors) {
                var field = this.find('name', error)[0];

                if (typeof field !== 'undefined' && field instanceof Ext.form.Field) {
                    field.markInvalid(__(this.module.toLowerCase() + '~form_errors_' + errors[error], 'base~form_errors_' + errors[error]));
                }
            }

            this.items.first().focus();
        }
    },

    /**
     * Cleans fields errors
     */
    cleanErrors: function() {
        this.items.each(function(item) {
            if (typeof item.items !== 'undefined' && item.items instanceof Ext.util.MixedCollection) {
                item.items.each(function(field) {
                    if (field instanceof Ext.form.Field) {
                        field.clearInvalid();
                    }
                });
            }
        }, this);
    }
});